﻿namespace AdvancedTraining.Lesson02;

public class ChooseWork
{
    /// <summary>
    /// 在SortedDictionary中找到小于等于target的最大键对应的值
    /// 等价于Java TreeMap的floorKey()然后获取值
    /// </summary>
    /// <param name="map">排序字典</param>
    /// <param name="target">目标值</param>
    /// <returns>小于等于target的最大键对应的值，如果不存在则返回0</returns>
    private static int FindFloorValue(SortedDictionary<int, int> map, int target)
    {
        var result = 0;
        foreach (var kvp in map)
        {
            if (kvp.Key <= target)
            {
                result = kvp.Value; // 更新为当前更优的报酬
            }
            else
            {
                break; // 因为字典是按key排序的，后面的key更大
            }
        }
        return result;
    }

    public static int[] GetMoneys(Job[] job, int[] ability)
    {
        Array.Sort(job, (x, y) => x.Hard != y.Hard ? x.Hard - y.Hard : y.Money - x.Money);
        // key : 难度   value：报酬
        var map = new SortedDictionary<int, int>
        {
            [job[0].Hard] = job[0].Money
        };
        // pre : 上一份进入map的工作
        var pre = job[0];
        for (var i = 1; i < job.Length; i++)
            if (job[i].Hard != pre.Hard && job[i].Money > pre.Money)
            {
                pre = job[i];
                map[pre.Hard] = pre.Money;
            }

        var ans = new int[ability.Length];
        for (var i = 0; i < ability.Length; i++)
        {
            // ability[i] 当前人的能力 <= ability[i]  且离它最近的
            // 使用自定义方法找到小于等于ability[i]的最大键对应的值
            ans[i] = FindFloorValue(map, ability[i]);
        }

        return ans;
    }

    public class Job(int m, int h)
    {
        public readonly int Hard = h;
        public readonly int Money = m;
    }

    /// <summary>
    /// 测试ChooseWork算法
    /// </summary>
    public static void Run()
    {
        Console.WriteLine("ChooseWork算法测试开始...");

        // 测试用例1
        var jobs1 = new[]
        {
            new Job(10, 1),
            new Job(20, 2),
            new Job(30, 3),
            new Job(40, 4),
            new Job(50, 5)
        };
        var ability1 = new[] { 0, 1, 2, 3, 4, 5, 6 };
        var result1 = GetMoneys(jobs1, ability1);
        Console.WriteLine($"测试1 - 工作报酬: [10,20,30,40,50], 能力: [0,1,2,3,4,5,6]");
        Console.WriteLine($"结果: [{string.Join(",", result1)}]");
        Console.WriteLine("期望: [0,10,20,30,40,50,50]");

        // 测试用例2 - 相同难度不同报酬
        var jobs2 = new[]
        {
            new Job(100, 1),
            new Job(200, 1),
            new Job(150, 2),
            new Job(300, 3),
            new Job(250, 3)
        };
        var ability2 = new[] { 1, 2, 3 };
        var result2 = GetMoneys(jobs2, ability2);
        Console.WriteLine($"\n测试2 - 工作报酬: [100,200,150,300,250], 难度: [1,1,2,3,3]");
        Console.WriteLine($"能力: [1,2,3]");
        Console.WriteLine($"结果: [{string.Join(",", result2)}]");
        Console.WriteLine("期望: [200,200,300] (修正：能力为2的人可以选择难度1的工作，报酬200)");

        // 测试用例3 - 复杂情况
        var jobs3 = new[]
        {
            new Job(50, 2),
            new Job(100, 3),
            new Job(200, 4),
            new Job(150, 3),
            new Job(120, 5),
            new Job(80, 1)
        };
        var ability3 = new[] { 1, 2, 3, 4, 5, 6 };
        var result3 = GetMoneys(jobs3, ability3);
        Console.WriteLine($"\n测试3 - 工作报酬: [50,100,200,150,120,80], 难度: [2,3,4,3,5,1]");
        Console.WriteLine($"能力: [1,2,3,4,5,6]");
        Console.WriteLine($"结果: [{string.Join(",", result3)}]");
        Console.WriteLine("期望: [80,80,150,200,200,200] (修正：选择难度<=能力的最高报酬工作)");

        Console.WriteLine("\nChooseWork算法测试完成!");
    }
}